package com.example.adminframework.service.impl;

import com.example.adminframework.constant.CommonConstant;
import com.example.adminframework.constant.SystemMonitoring;
import com.example.adminframework.model.bo.*;
import com.example.adminframework.model.vo.SystemMonitoringVO;
import com.example.adminframework.service.SysMonitoringService;
import com.example.adminframework.util.DateUtil;
import com.sun.management.OperatingSystemMXBean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.text.DecimalFormat;
import java.util.*;

@Service
public class SysMonitoringServiceImpl implements SysMonitoringService {
    private static final Logger log = LoggerFactory.getLogger(SysMonitoringServiceImpl.class);
    // 保留小数点后两位
    private DecimalFormat decimalFormat = new DecimalFormat("#.00");

    private OperatingSystemMXBean operatingSystemMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();

    /**
     * 获取系统信息
     * @return
     */
    @Override
    public SystemMonitoringVO querySystemMonitorInfo() {
        SystemMonitoringVO systemMonitoringVO = new SystemMonitoringVO();
        // 设置服务器信息
        systemMonitoringVO.setServersMonitorInfo(getServersMessage());
        // 设置cpu信息
        systemMonitoringVO.setCpuMonitorInfo(getCpuMessage());
        // 设置磁盘信息
        systemMonitoringVO.setDiskMonitorInfoList(getDiskMessage());
        // 设置java虚拟机信息
        systemMonitoringVO.setJvmMonitorInfo(getJVMMessage());
        // 设置内存信息
        systemMonitoringVO.setMemoryMonitorInfo(getMemoryMessage());
        return systemMonitoringVO;
    }

    /**
     * 获取cpu相关信息
     * @return
     */
    private CpuMonitorInfo getCpuMessage(){
        CpuMonitorInfo cpuMonitorInfo = new CpuMonitorInfo();
        // 设置核心数
        cpuMonitorInfo.setCore(String.valueOf(Runtime.getRuntime().availableProcessors()));
        // 获取系统使用率
        double cpuLoad = operatingSystemMXBean.getSystemCpuLoad();
        cpuMonitorInfo.setSystemFrequencyUtilization(dfFormat(cpuLoad)+"%");
        // 总量（vacancyRate） - 使用率 (cpuLoad) = 空闲率
        double  vacancyRate = 1.00;
        vacancyRate = (vacancyRate - cpuLoad);
        cpuMonitorInfo.setVacancyRate(dfFormat(vacancyRate)+"%");
        // 获取用户使用率，并设置
        double userFrequencyUtilization = operatingSystemMXBean.getProcessCpuLoad();
        cpuMonitorInfo.setUserFrequencyUtilization(dfFormat(userFrequencyUtilization)+"%");
        return cpuMonitorInfo;
    }

    /**
     * 获取内存相关信息
     */
    private MemoryMonitorInfo getMemoryMessage(){
        MemoryMonitorInfo memoryMonitorInfo = new MemoryMonitorInfo();
        // 获取系统总内存，赋值
        double totalMemorySize = operatingSystemMXBean.getTotalPhysicalMemorySize() / SystemMonitoring.GB;
        memoryMonitorInfo.setTotalMemory(decimalFormat.format(totalMemorySize)+SystemMonitoring.GB_STR);
        // 获取系统已用内存，赋值
        double freeMemorySize = operatingSystemMXBean.getFreePhysicalMemorySize() / SystemMonitoring.GB;
        memoryMonitorInfo.setResidueMemory(decimalFormat.format(freeMemorySize)+SystemMonitoring.GB_STR);
        // 获取剩余内存  赋值
        double usedMemorySize = (totalMemorySize - freeMemorySize);
        memoryFormat(usedMemorySize);
        memoryMonitorInfo.setUseMemory(memoryFormat(usedMemorySize)+SystemMonitoring.GB_STR);
        // 获取使用率 赋值
        double useProportion = usedMemorySize/totalMemorySize*100;
        memoryMonitorInfo.setUseProportion(memoryFormat(useProportion)+"%");
        // jvm内存信息
        double totalMemory = Runtime.getRuntime().totalMemory() / SystemMonitoring.MB;
        double freeMemory = Runtime.getRuntime().freeMemory() / SystemMonitoring.MB;
        // 获取jvm总内存 赋值
        double jvmTotalMemory = totalMemory + freeMemory;
        memoryMonitorInfo.setJvmTotalMemory(decimalFormat.format(jvmTotalMemory)+SystemMonitoring.MB_STR);
        // 获取jvm的使用率 赋值
        double jvmUseProportion = (freeMemory/jvmTotalMemory)*100;
        memoryMonitorInfo.setJvmUseProportion(decimalFormat.format(jvmUseProportion)+"%");
        // 获取jvm已用内存 赋值
        memoryMonitorInfo.setJvmUseMemory(decimalFormat.format(freeMemory)+SystemMonitoring.MB_STR);
        // 获取jvm剩余内存 赋值
        memoryMonitorInfo.setJvmResidueMemory(decimalFormat.format(totalMemory)+SystemMonitoring.MB_STR);
        return memoryMonitorInfo;
    }

    /**
     * 获取java虚拟机相关信息
     * @return
     */
    private JVMMonitorInfo getJVMMessage(){
        JVMMonitorInfo jvmMonitorInfo = new JVMMonitorInfo();
        // 获取虚拟机的运行时系统的管理接口
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        // jvm名称
        jvmMonitorInfo.setName(runtime.getVmName());
        // 获取java版本  赋值
        jvmMonitorInfo.setJavaVersion(System.getProperty(SystemMonitoring.JAVA_VERSION));
        // 获取启动时间  赋值
        jvmMonitorInfo.setStartDate(new Date(runtime.getStartTime()));
        // 获取运行时间  赋值
        jvmMonitorInfo.setOperationDate(DateUtil.formatDuring(runtime.getUptime()));
        // 获取系统属性
        Properties props=System.getProperties();
        // 获取jvm安装路径 赋值
        jvmMonitorInfo.setInstallUrl(props.getProperty(SystemMonitoring.JAVA_HOME));
        // 获取项目路径 赋值
        jvmMonitorInfo.setProjectUrl(System.getProperty(SystemMonitoring.USER_DIR));
        return jvmMonitorInfo;
    }

    /**
     *获取服务器相关信息
     */
    private ServersMonitorInfo getServersMessage(){
        // 获取系统属性
        Properties props=System.getProperties();
        ServersMonitorInfo serversMonitorInfo = new ServersMonitorInfo();
        try {
            // 获取服务器信息
            InetAddress localhost = InetAddress.getLocalHost();
            // 获取操作系统名称  赋值
            serversMonitorInfo.setServersSystemName(props.getProperty(SystemMonitoring.OS_NAME));
            // 获取操作系统架构  赋值
            serversMonitorInfo.setSystemFramework(props.getProperty(SystemMonitoring.OS_ARCH));
            // 获取服务器名称  赋值
            serversMonitorInfo.setServersName(localhost.getHostName());
            // 获取网卡信息  赋值
            serversMonitorInfo.setNetworkCardMonitorInfoList(getNetworkCardMessage());
            // 获取服务器ip  赋值
            serversMonitorInfo.setServersIp(localhost.getHostAddress());
        } catch (UnknownHostException e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return serversMonitorInfo;
    }

    /**
     * 获取网卡相关信息集合
     */
    private List<NetworkCardMonitorInfo> getNetworkCardMessage(){
        List<NetworkCardMonitorInfo> networkCardBoList = new ArrayList<>();
        try {
            Enumeration<NetworkInterface> nets  = NetworkInterface.getNetworkInterfaces();
            for (NetworkInterface networkInterface : Collections.list(nets)) {
                NetworkCardMonitorInfo networkCardMonitorInfo = getNetworkCardMessage(networkInterface);
                networkCardBoList.add(networkCardMonitorInfo);
            }
        } catch (SocketException e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return networkCardBoList;
    }

    /**
     * 获取网卡信息
     * @param networkInterface
     * @return
     */
    private NetworkCardMonitorInfo getNetworkCardMessage(NetworkInterface networkInterface){
        NetworkCardMonitorInfo networkCardMonitorInfo = new NetworkCardMonitorInfo();
        // 获取以太网适配器名称  赋值
        networkCardMonitorInfo.setName(networkInterface.getDisplayName());
        Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            // 获取的ip是： /x.x.x.x格式 截取开头的一位
            String ip = inetAddress.toString().substring(1, inetAddress.toString().length());
            if (matchesIpv4(ip)) {
                // 根据正则过滤ipv4
                networkCardMonitorInfo.setIpv4(ip);
            }
            if (matchesIpv6(ip)){
                // 根据正则过滤ipv6
                networkCardMonitorInfo.setIpv6(ip);
            }
        }
        return networkCardMonitorInfo;
    }

    /**
     * 获取磁盘相关信息
     * @return
     */
    private List<DiskMonitorInfo> getDiskMessage() {
        List<DiskMonitorInfo> list = new ArrayList<DiskMonitorInfo>();
        FileSystemView sys = FileSystemView.getFileSystemView();
        // 获取磁盘分区列表
        File[] files = File.listRoots();
        for (File file : files) {
            DiskMonitorInfo diskMonitorInfo  = new  DiskMonitorInfo();
            // 获取可用容量
            long freeSpace=file.getFreeSpace();
            // 获取总磁盘容量
            long totalSpace=file.getTotalSpace();
            // 获取已用磁盘容量
            long usableSpace=totalSpace-freeSpace;
            // 获取盘符路径
            diskMonitorInfo.setDiskUrl(file.getPath());
            // 获取总容量  赋值
            diskMonitorInfo.setTotal(formatting(totalSpace));
            // 获取可用容量  赋值
            diskMonitorInfo.setUsableSize(formatting(freeSpace));
            // 已用容量  赋值
            diskMonitorInfo.setUsedSize(formatting(usableSpace));
            // 获取占用率  赋值
            diskMonitorInfo.setUsedPercentage(decimalFormat.format(((double)usableSpace/(double)totalSpace)*100)+"%");
            // 获取磁盘类型  赋值
            diskMonitorInfo.setDisType(sys.getSystemTypeDescription(file));
            list.add(diskMonitorInfo);
        }
        return list;
    }

    /**
     * 判断参数是否不为0
     * @param number
     * @return
     */
    private String dfFormat(double number){
        String numberString = String.valueOf(number * 100);
        if (number == 0){
            return numberString;
        }
        if (numberString.length() >= 5){
            return numberString.substring(0,5);
        }
        return numberString;
    }

    /**
     * 内存数据格式化
     * @param number
     * @return
     */
    private String memoryFormat(double number){
        String numberString = String.valueOf(number);
        if (number == 0){
            return numberString;
        }
        return numberString.substring(0,4);
    }

    /**
     * ipv6正则验证
     * @param ip
     */
    private boolean matchesIpv6(String ip){
        if (ip == null) {
            return false;
        }
        return ip.matches(CommonConstant.IPV4_VERIFY);
    }

    /**
     * ipv4正则验证
     * @param ip
     */
    private boolean matchesIpv4(String ip){
        if (ip == null) {
            return false;
        }
        return ip.matches(CommonConstant.IPV6_VERIFY);

    }

    /**
     * 对磁盘容量进行格式化
     * @param diskSize
     * @return
     */
    private String formatting(Long diskSize){
        return decimalFormat.format(diskSize / SystemMonitoring.GB) + SystemMonitoring.GB_STR;
    }
}
